﻿package com.gui.scrollbar {
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	
	/**
	 * ...
	 * @author Ricardo Teixeira
	 */
	public class DisplayObjectScrollBar extends Sprite {
		
		private var dragArea:Sprite;
		private var background:MovieClip;
		private var drag:MovieClip;
		private var down:SetaBaixo;
		private var up:SetaCima;
		private var left:SetaEsq;
		private var right:SetaDir;
		
		private var _autoPosition:Boolean;
		private var isVertical:Boolean;
		private var conteiner:DisplayObject;
		private var backgroundHeight:Number;
		private var backgroundWidth:Number;
		
		private var _scrollLength:Number;
		
		private var rectMask:Rectangle;
		
		private var box:Sprite;
		private var perc:Number;

		public function DisplayObjectScrollBar (conteiner:DisplayObject, vertical:Boolean = true, auto:Boolean = true, length:Number = 300) {
			this.conteiner = conteiner;
			this.scrollLength = length;
			
			this.box = new Sprite ();
			this.box.x = this.conteiner.x;
			this.box.y = this.conteiner.y;
			
			var pai:DisplayObjectContainer = this.conteiner.parent;
			pai.addChild (this.box);		
			
			this.box.addChild (this.conteiner);			
						
			this.conteiner.x = 0;
			this.conteiner.y = 0;
			
			this.autoPosition = auto;
			this.isVertical = vertical;
			
			this.addEventListener (Event.ENTER_FRAME, onFrame);	
		}
				
		public function resize (length:Number):void {
			this.scrollLength = length;
			this.addEventListener (Event.ENTER_FRAME, onFrame);	
		}
		
		public function update ():void {			
			this.addEventListener (Event.ENTER_FRAME, onFrame);	
		}
		
		private function initHorizontal ():void {
			if (this.left != null) {
				this.dragArea.removeChild (this.background);
				this.dragArea.removeChild (this.drag);
				this.removeChild (this.dragArea);
				this.removeChild (this.left);
				this.removeChild (this.right);
				
				this.left = null;
				this.right = null;
				this.drag = null;
				this.background = null;
				this.dragArea = null;
			}
			
			this.left = new SetaEsq ();
			this.right = new SetaDir ();
			this.drag = new DragH ();
			this.background = new BackgroundH ();
			this.dragArea = new Sprite ();
			
			this.background.width = this.scrollLength - (this.right.width * 2) - 10;			
			this.backgroundWidth = this.background.width;
			
			var difPosY:Number = Math.abs (this.left.height - this.background.height) / 2;
			
			this.drag.width = (this.background.width / this.conteiner.width) * this.drag.width;
			if (this.drag.width < 20) {
				this.drag.width = 20;
			}
			
			this.dragArea.x = this.left.width + 5;
			this.dragArea.y = difPosY / 2;
			
			this.drag.x = this.background.x;
			this.drag.y = this.background.y;
						
			this.left.addEventListener (MouseEvent.CLICK, onClickLeft);
			this.right.addEventListener (MouseEvent.CLICK, onClickRight);
			
			this.drag.addEventListener (MouseEvent.MOUSE_DOWN, onDownDrag);
			this.drag.addEventListener (MouseEvent.MOUSE_UP, onUpDrag);
			
			this.background.addEventListener (MouseEvent.CLICK, onClickBg);
			
			this.addChild (this.dragArea);
			this.dragArea.addChild (this.background);
			this.dragArea.addChild (this.drag);
			this.addChild (this.left);
			this.addChild (this.right);
			
			this.right.x = this.dragArea.x + this.dragArea.width + 5;
		}
		
		private function initVertical ():void {
			if (this.up != null) {
				this.dragArea.removeChild (this.background);
				this.dragArea.removeChild (this.drag);
				this.removeChild (this.dragArea);
				this.removeChild (this.up);
				this.removeChild (this.down);
				
				this.up = null;
				this.down = null;
				this.drag = null;
				this.background = null;
				this.dragArea = null;
			}
			
			this.up = new SetaCima  ();
			this.down = new SetaBaixo ();
			this.drag = new DragV ();
			this.background = new BackgroundV ();
			this.dragArea = new Sprite ();
			
			this.background.height = this.scrollLength - (this.up.height * 2) - 10;;
			this.backgroundHeight = this.background.height;
			
			var difPosX:Number = Math.abs (this.up.width - this.background.width) / 2;
			
			this.drag.height = (this.background.height / this.conteiner.height) * this.drag.height;
			if (this.drag.height < 20) {
				this.drag.height = 20;
			}
			
			this.dragArea.x = difPosX / 2;
			this.dragArea.y = this.up.height + 5;
			this.down.y = this.dragArea.y + this.background.height + 5;
						
			this.up.addEventListener (MouseEvent.CLICK, onClickUp);
			this.down.addEventListener (MouseEvent.CLICK, onClickDown);
			
			this.drag.addEventListener (MouseEvent.MOUSE_DOWN, onDownDrag);
			this.drag.addEventListener (MouseEvent.MOUSE_UP, onUpDrag);
			
			this.background.addEventListener (MouseEvent.CLICK, onClickBg);
			
			this.addChild (this.dragArea);
			this.dragArea.addChild (this.background);
			this.dragArea.addChild (this.drag);
			this.addChild (this.down);
			this.addChild (this.up);
		}
		
		private function onInit(e:Event = null):void{
			if (this.isVertical) {
				this.initVertical ();
			} else {
				this.initHorizontal ();
			}			
		}
		
		private function onFrame(e:Event):void {
			if (this.conteiner.width > 0) {	
				this.removeEventListener (Event.ENTER_FRAME, onFrame);
				if (this.isVertical) {							
					if (this.scrollLength >= this.conteiner.height) {
						return;
					}					
				} else {									
					if (this.scrollLength >= this.conteiner.width) {
						return;
					}
				}
				
				this.onInit ();


				if (this.isVertical) {
					this.rectMask = new Rectangle (0, 0, this.conteiner.width, this.scrollLength); 
				} else {
					this.rectMask = new Rectangle (0, 0, this.scrollLength, this.conteiner.height); 
				}
				
				this.box.scrollRect = this.rectMask;
			}
		}
				
		private function onFrameDrag (e:Event):void {			
			if (this.isVertical) {
				var yMax:Number = this.conteiner.height - this.rectMask.height;
				this.perc = Math.round (this.drag.y / (this.background.height - this.drag.height) * 100);
				
				var yRect:Number = (this.perc * yMax) / 100;
				var yRectFinal:Number = this.box.scrollRect.y;
				yRectFinal += (yRect - yRectFinal) / 10;
				
				this.box.scrollRect = new Rectangle (0, yRectFinal, this.rectMask.width, this.rectMask.height);
			} else { 
				var xMax:Number = this.conteiner.width - this.rectMask.width;
				this.perc = Math.round (this.drag.x / (this.background.width - this.drag.width) * 100);
				
				var xRect:Number = (this.perc * xMax) / 100;
				var xRectFinal:Number = this.box.scrollRect.x;
				xRectFinal += (xRect - xRectFinal) / 10;
				
				this.box.scrollRect = new Rectangle (xRectFinal, 0, this.rectMask.width, this.rectMask.height);
			} 			
		}
		
		private function onClickDown(e:MouseEvent):void {			
			var yMax:Number = this.conteiner.height - this.rectMask.height;
			
			var yRect:Number = this.box.scrollRect.y;
			yRect += 10;
			if (yRect > yMax) {
				yRect = yMax;
			}
			
			var percYDrag:Number = yRect / yMax;
			this.drag.y = percYDrag * (this.backgroundHeight - this.drag.height);
			
			this.box.scrollRect = new Rectangle (0, yRect, this.rectMask.width, this.rectMask.height);
		}
		
		private function onDownDrag(e:MouseEvent):void {
			var rect:Rectangle;
			if (this.isVertical) {
				rect = new Rectangle (0, 0, this.drag.x, this.background.height - this.drag.height);
				this.drag.startDrag (false, rect);			
				this.drag.addEventListener (MouseEvent.MOUSE_MOVE, onDragMove);
				this.stage.addEventListener (MouseEvent.MOUSE_MOVE, onDragMove);
				this.stage.addEventListener (MouseEvent.MOUSE_UP, onUpDrag);
			} else {
				rect = new Rectangle (0, 0, this.background.width - this.drag.width, this.drag.y);
				this.drag.startDrag (false, rect);			
				this.drag.addEventListener (MouseEvent.MOUSE_MOVE, onDragMove);
				this.stage.addEventListener (MouseEvent.MOUSE_MOVE, onDragMove);
				this.stage.addEventListener (MouseEvent.MOUSE_UP, onUpDrag);
			}
			/*if (this.hasEventListener (Event.ENTER_FRAME)) {
				this.removeEventListener (Event.ENTER_FRAME, onFrameDrag);
			}
			this.addEventListener (Event.ENTER_FRAME, onFrameDrag);*/
		}
		
		private function onUpDrag(e:MouseEvent):void { 
			this.drag.stopDrag ();
			this.stage.removeEventListener (MouseEvent.MOUSE_MOVE, onDragMove);
			this.stage.removeEventListener (MouseEvent.MOUSE_UP, onUpDrag);
		}
		
		private function onDragMove(e:MouseEvent):void { 
			if (this.isVertical) {
				var yMax:Number = this.conteiner.height - this.rectMask.height;
				this.perc = Math.round (this.drag.y / (this.background.height - this.drag.height) * 100);
				
				var yRect:Number = (this.perc * yMax) / 100;
				
				this.box.scrollRect = new Rectangle (0, yRect, this.rectMask.width, this.rectMask.height);
			} else { 
				var xMax:Number = this.conteiner.width - this.rectMask.width;
				this.perc = Math.round (this.drag.x / (this.background.width - this.drag.width) * 100);
				
				var xRect:Number = (this.perc * xMax) / 100;
				
				this.box.scrollRect = new Rectangle (xRect, 0, this.rectMask.width, this.rectMask.height);
			} 	
		}
		
		private function onClickUp(e:MouseEvent):void {
			var yMax:Number = this.conteiner.height - this.rectMask.height;
			
			var yRect:Number = this.box.scrollRect.y;
			yRect -= 10;
			if (yRect < 0) {
				yRect = 0;
			}
			
			var percYDrag:Number = yRect / yMax;
			this.drag.y = percYDrag * (this.backgroundHeight - this.drag.height);
			
			this.box.scrollRect = new Rectangle (0, yRect, this.rectMask.width, this.rectMask.height);
		}
				
		private function onClickRight(e:MouseEvent):void {
			var xMax:Number = this.conteiner.width - this.rectMask.width;
				
			var xRect:Number = this.box.scrollRect.x;
			xRect += 10;
			if (xRect > xMax) {
				xRect = xMax;
			}
			var percXDrag:Number = xRect / xMax;
			this.drag.x = percXDrag * (this.backgroundWidth - this.drag.width);
			
			this.box.scrollRect = new Rectangle (xRect, 0, this.rectMask.width, this.rectMask.height);
		}
		
		private function onClickLeft(e:MouseEvent):void {
			var xMax:Number = this.conteiner.width - this.rectMask.width;
				
			var xRect:Number = this.box.scrollRect.x;
			xRect -= 10;
			if (xRect < 0) {
				xRect = 0;
			}
			var percXDrag:Number = xRect / xMax;
			this.drag.x = percXDrag * (this.backgroundWidth - this.drag.width);
			
			this.box.scrollRect = new Rectangle (xRect, 0, this.rectMask.width, this.rectMask.height);
		}
		
		private function onClickBg(e:MouseEvent):void {
			if (this.isVertical) {
				var yMax:Number = this.backgroundHeight - this.drag.height;
				var yDrag:Number = this.dragArea.mouseY - (this.drag.height / 2);
				
				if (yDrag > yMax) {
					yDrag = yMax;
				}
				if (yDrag < 0) {
					yDrag = 0;
				}
				
				this.drag.y = yDrag;
				
				this.onDragMove (null);
			} else {
				var xMax:Number = this.backgroundWidth - this.drag.width;
				var xDrag:Number = this.dragArea.mouseX - (this.drag.width / 2);
				
				if (xDrag > xMax) {
					xDrag = xMax;
				}
				if (xDrag < 0) {
					xDrag = 0;
				}
				
				this.drag.x = xDrag;
				
				this.onDragMove (null);
			}
		}
		
		public function get autoPosition():Boolean { return _autoPosition; }
		
		public function set autoPosition(value:Boolean):void {
			_autoPosition = value;
		}
		
		public function get scrollLength():Number { return _scrollLength; }
		
		public function set scrollLength(value:Number):void {
			_scrollLength = value;
		}
		
	}
	
}